package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.sc.nft.dao.*;
import com.sc.nft.dto.EcologyHatchConfDao;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.ConversionNftDTO;
import com.sc.nft.entity.dto.GasConsumeDTO;
import com.sc.nft.entity.vo.QueryBoxConditionVO;
import com.sc.nft.entity.vo.WhetherUserMeetsRedemptionConditionsVO;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * 盲盒抽奖池服务接口实现
 *
 * @author 张翔宇
 * @description 盲盒抽奖池
 * @since 2023-04-03 18:03:44
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class BoxTakePoolServiceImpl implements BoxTakePoolService {

    private final BoxTakePoolDao boxTakePoolDao;

    private final UserConsensusService userConsensusService;

    private final EcologyHatchConfDao ecologyHatchConfDao;

    private final DigitalCollectionProductInfoDao digitalCollectionProductInfoDao;

    private final ProductStockService productStockService;

    private final BoxTakeConversionConditionService boxTakeConversionConditionService;

    private final UserCollectionService userCollectionService;

    private final DigitalCollectionDao digitalCollectionDao;

    private final ProductStockDao productStockDao;

    private final UserEquityPropsService equityPropsService;

    private final UserAssetsService userAssetsService;

    private final EcologyPoolService ecologyPoolService;
    private final OrderGasService orderGasService;

    @SneakyThrows
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean conversion(ConversionNftDTO conversionNftDTO, UserInfo userInfo) {
        // 验证用户是否有足够的凭证
        BoxTakePool boxTakePool = boxTakePoolDao.getById(conversionNftDTO.getId());
        Assert.isTrue(boxTakePool.getStatus(), () -> new GlobalRunTimeException(ErrorCode.PRODUCT_HAS_BEEN_DESCONTINUED));

        DigitalCollectionProductInfo digitalCollectionProductInfo = digitalCollectionProductInfoDao.getById(boxTakePool.getProductBoxId());
        // 凭证数量足够.扣除凭证数量
        WhetherUserMeetsRedemptionConditionsVO satisfactoryConvertibility = boxTakeConversionConditionService.whetherUserMeetsRedemptionConditions(userInfo.getId(), conversionNftDTO.getId(), conversionNftDTO.getQuantity());
        if (BeanUtil.isEmpty(satisfactoryConvertibility)) {
            throw new GlobalRunTimeException("该藏品暂无兑换,可联系官方客服");
        }
        
       
        if (satisfactoryConvertibility.comparison()) {
            // 扣除凭证和积分
            if (satisfactoryConvertibility.whetherEquityPropsAreNeeded()) {
                List<QueryBoxConditionVO> equityProps = satisfactoryConvertibility.screen(2, BoxConditionEnum.EQUITY_PROPS);
                equityProps.forEach(queryBoxConditionVO -> {
                    equityPropsService.subVoucher(queryBoxConditionVO.getTripartiteId(), userInfo.getId(), Convert.toInt(queryBoxConditionVO.getCostQuantity()) * conversionNftDTO.getQuantity(), StrUtil.format("{}x{}", digitalCollectionProductInfo.getFirstTitle(), conversionNftDTO.getQuantity()), boxTakePool.getId(), EquityPropsTypeEnum.VOUCHER, EquityPropsTypeEnum.VIRTUAL_PROPS, EquityPropsTypeEnum.RAFFLE_TICKET);
                });
            }

            if (satisfactoryConvertibility.whetherFragmentsAreNeeded()) {
                List<QueryBoxConditionVO> starFragment = satisfactoryConvertibility.screen(2, BoxConditionEnum.STAR_FRAGMENT);
                starFragment.forEach(queryBoxConditionVO -> {
                    userAssetsService.subIntegralByUserId(Convert.toBigDecimal(queryBoxConditionVO.getCostQuantity()).multiply(Convert.toBigDecimal(conversionNftDTO.getQuantity())), userInfo.getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.BOX_EXCHANGE, boxTakePool.getId(), StrUtil.format("{}x{}", digitalCollectionProductInfo.getFirstTitle(), conversionNftDTO.getQuantity()));
                });
            }

            //生态积分
            if (satisfactoryConvertibility.whetherEcologyPoolPointsNeeded()) {
                List<QueryBoxConditionVO> ecologyPools = satisfactoryConvertibility.screen(2, BoxConditionEnum.ECOLOGY_POOL_POINTS);
                ecologyPools.forEach(queryBoxConditionVO -> {
                    ecologyPoolService.convertPoints(Convert.toBigDecimal(queryBoxConditionVO.getCostQuantity()).multiply(Convert.toBigDecimal(conversionNftDTO.getQuantity())), boxTakePool.getDaoId(), userInfo.getId());
                });
            }

            // 发放NFT
            // 扣除库存
            ProductStock productStock = productStockDao.getProductStock(digitalCollectionProductInfo.getId(), digitalCollectionProductInfo.getRelationId(), null);
            Assert.isTrue(productStock.getUsableCount() >= conversionNftDTO.getQuantity(), () -> new GlobalRunTimeException(ErrorCode.UNDEREXCHANGE));
            Assert.isFalse(productStock.getUsableCount() == 0, () -> new GlobalRunTimeException(ErrorCode.COLLECTION_IS_SOLD_OUT));
            productStockService.deductStock(digitalCollectionProductInfo.getId(), digitalCollectionProductInfo.getRelationId(), conversionNftDTO.getQuantity(), userInfo.getId(), CommodityType.EXCHANGE_COLLECTION);
            DigitalCollection digitalCollection = digitalCollectionDao.getById(digitalCollectionProductInfo.getRelationId());
            
            if (boxTakePool.getGasConf()){
                //藏品兑换上链费
                GasConsumeDTO gasConsume=new GasConsumeDTO();
                gasConsume.setConsumeCost(boxTakePool.getConsumeCost());
                gasConsume.setUserId(userInfo.getId());
                gasConsume.setGasConsumeType(GasConsumeTypeEnum.BALANCE);
                gasConsume.setWalletDetailType(WalletDetailTypeEnum.GAS_CONVERSION);
                gasConsume.setProductId(productStock.getProductId());
                gasConsume.setCollectionId(digitalCollection.getId());
                gasConsume.setOrderGasType(OrderGasTypeEnum.GAS_CONVERSION);
                orderGasService.gasConsume(gasConsume);
            }
            
            // 给用户发NFT
            for (int i = 0; i < conversionNftDTO.getQuantity(); i++) {
                UserCollection userCollection = userCollectionService.addCollectionForExchange(userInfo.getId(), null,
                        digitalCollectionProductInfo.getRelationId(), IdUtil.getSnowflakeNextIdStr(), digitalCollection.getCreationContent(),
                        digitalCollection.getLevel(), digitalCollection.getFirstTitle(),
                        digitalCollection.getUserCreatorId(), ReceivedCollectionType.EXCHANGE_COLLECTION, null,
                        null, null, true, digitalCollectionProductInfo.getId(), 0L,
                        0L, digitalCollectionProductInfo.getProductNum(), 0, null, null, AddCollectionEnum.STAIR, conversionNftDTO.getId());
                //藏品流转表记录
                CollectionCirculatingRecord collectionCirculatingRecord = new CollectionCirculatingRecord();
                collectionCirculatingRecord.setUserId(userInfo.getId());
                collectionCirculatingRecord.setCollectionId(digitalCollection.getId());
                collectionCirculatingRecord.setCommodityType(CommodityType.EXCHANGE_COLLECTION);
                collectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
                collectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.EXCHANGE_COLLECTION);
                collectionCirculatingRecord.setToUserCollection(userCollection.getId());
                collectionCirculatingRecord.setOrderId(0L);
                collectionCirculatingRecord.setNumber(1);
                collectionCirculatingRecord.insert();
            }
            if(digitalCollection.getCollectionType()==DigitalMarketTypeEnum.ECOLOGY){
                userConsensusService.adjustConsensusService(userInfo.getId(),digitalCollection.getId() ,BigDecimal.valueOf(conversionNftDTO.getQuantity()),UserConsensusTypeEnums.EXCHANGE,digitalCollection.getFirstTitle(),null);
            }
            return true;
        } else {
            throw new GlobalRunTimeException("不满足兑换条件");
        }
    }

}
